Load libraries.

library(Seurat)
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio
Registered S3 method overwritten by 'spatstat.geom':
  method     from
  print.boxx cli 
Attaching SeuratObject
Warning message:
R graphics engine version 14 is not supported by this version of RStudio. The Plots tab will be disabled until a newer version of RStudio is installed. 
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse 1.3.1 ──
✓ ggplot2 3.3.5     ✓ purrr   0.3.4
✓ tibble  3.1.6     ✓ dplyr   1.0.7
✓ tidyr   1.1.4     ✓ stringr 1.4.0
✓ readr   2.1.1     ✓ forcats 0.5.1
── Conflicts ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
library(pracma)

Attaching package: ‘pracma’

The following object is masked from ‘package:purrr’:

    cross

Load seurat object.

load("/Volumes/Bud_SSD/20210505-seurat/all-aggr-seurat.Robj")

Explore meta data.

head(all.aggr@meta.data)

Plot histogram of number of umi’s.

ggplot(data = all.aggr@meta.data, mapping = aes(x = nCount_RNA)) +
  geom_histogram() +
  geom_vline(xintercept = mean(all.aggr$nCount_RNA), color = "blue") +
  geom_vline(xintercept = median(all.aggr$nCount_RNA), color = "red") +
  scale_x_continuous(trans = "log10")

Looks normal except for bump on left.

Plot histogram of number of umi’s. Color by embryo.

ggplot(data = all.aggr@meta.data, mapping = aes(x = nCount_RNA, color = embryo.id)) +
  geom_histogram() +
  scale_x_continuous(trans = "log10") + 
  facet_wrap(~embryo.id)

Bump on left due to ATU6-45 and BBH6-59.

What are the genotypes of these two embryos? Which experiments did they come from?

print("ATU6-45")
[1] "ATU6-45"
(all.aggr@meta.data %>% filter(embryo.id == "ATU6-45") %>% pull(genotype))[1]
[1] "FIN"
(all.aggr@meta.data %>% filter(embryo.id == "ATU6-45") %>% pull(experiment))[1]
[1] "20171003"
print("AYR4-22")
[1] "AYR4-22"
(all.aggr@meta.data %>% filter(embryo.id == "AYR4-22") %>% pull(genotype))[1]
[1] "FIN"
(all.aggr@meta.data %>% filter(embryo.id == "AYR4-22") %>% pull(experiment))[1]
[1] "20180515"

Both mutant. But from two different experiments.

Plot histogram of number of genes.

ggplot(data = all.aggr@meta.data, mapping = aes(x = nFeature_RNA)) +
    geom_histogram() +
    geom_vline(xintercept = mean(all.aggr$nFeature_RNA), color = "blue") +
  geom_vline(xintercept = median(all.aggr$nFeature_RNA), color = "red")

Looks similar to histogram of number of umi’s. More normal. Except for bump on left again.

Plot histogram of number of genes. Color by embryo.

ggplot(data = all.aggr@meta.data, mapping = aes(x = nFeature_RNA, color = embryo.id)) +
  geom_histogram() +
  facet_wrap(~embryo.id)

Bump is due to same two embryos earlier. ATU6-45 and AYR4-22.

Calculate % mitochondrial genes.

all.aggr[["percent.mt"]] <- PercentageFeatureSet(all.aggr, pattern = "^mt-")
head(all.aggr@meta.data)

Plot histogram of % mitochondrial genes.

ggplot(data = all.aggr@meta.data, mapping = aes(x = percent.mt)) +
  geom_histogram() +
    geom_vline(xintercept = mean(all.aggr$percent.mt), color = "blue") +
  geom_vline(xintercept = median(all.aggr$percent.mt), color = "red") +
  scale_x_continuous(trans = "log10")

Largest portion of distribution normal. Obvious hump of cells with low % mitochondrial genes. Odd that they have low % mitochondrial genes. Usually low is better, but here, most cells have a % between 1 and 10.

Are these cells associated with one embryo?

ggplot(data = all.aggr@meta.data, mapping = aes(x = percent.mt, color = embryo.id)) +
  geom_histogram() +
  scale_x_continuous(trans = "log10") +
  facet_wrap(~embryo.id, scales = "free_y")

Left bump due to more than one embryo. Pervasive feature.

% mitochondrial genes is dependent on number of genes detected. Do these correpond to cells with low numbers of genes?

ggplot(data = all.aggr@meta.data, mapping = aes(x = percent.mt, y = nFeature_RNA)) +
  geom_point(size = 0.1) +
      geom_vline(xintercept = mean(all.aggr$percent.mt), color = "blue") +
  geom_vline(xintercept = median(all.aggr$percent.mt), color = "red") +
  scale_x_continuous(trans = "log10")

So the cells with low mito tend to have lower number of genes. mito seems to distribute normally along number of genes. But if we only filter these out, it doesn’t account for upper range.

Calculate outliers using median absolute deviation.

all.aggr$log.mito <- log10(all.aggr$percent.mt)
median.mito <- median(all.aggr$log.mito)
all.aggr$d.mito <- abs(all.aggr$log.mito - median.mito)
md.mito <- mad(all.aggr$log.mito)
all.aggr$mito.out <- all.aggr$d.mito > md.mito*3
sum(all.aggr$mito.out)
[1] 2256
ggplot(data = all.aggr@meta.data, mapping = aes(x = percent.mt, y = nFeature_RNA, color = mito.out)) +
  geom_point(size = 0.1) +
  scale_x_continuous(trans = "log10")

What does histogram of % mito now look?

ggplot(data = all.aggr@meta.data, mapping = aes(x = percent.mt, color = mito.out)) +
  geom_histogram() +
  scale_x_continuous(trans = "log10")

Genes?

ggplot(data = all.aggr@meta.data, mapping = aes(x = nFeature_RNA, color = mito.out)) +
  geom_histogram()

UMIs?

ggplot(data = all.aggr@meta.data, mapping = aes(x = nCount_RNA, color = mito.out)) +
  geom_histogram() +
  scale_x_continuous(trans = "log10")

Can we find outliers among genes after already filtering out outliers from mito?

median.gene <- median(all.aggr@meta.data %>% filter(mito.out == FALSE) %>% pull(nFeature_RNA))
all.aggr$d.gene <- abs(all.aggr$nFeature_RNA - median.gene)
md.gene <- mad(all.aggr@meta.data %>% filter(mito.out == FALSE) %>% pull(nFeature_RNA))
all.aggr$gene.out <- all.aggr$d.gene > md.gene*3
sum(all.aggr$gene.out)
[1] 221

So 221 cells can be filtered out after already filtering out outliers from mito.

Where do these cells lie along histogram of number of genes?

ggplot(data = all.aggr@meta.data %>% filter(mito.out == FALSE), mapping = aes(x = nFeature_RNA, color = gene.out)) +
  geom_histogram()

Captured those in upper range.

Along number of umis?

ggplot(data = all.aggr@meta.data %>% filter(mito.out == FALSE), mapping = aes(x = nCount_RNA, color = gene.out)) +
  geom_histogram() +
  scale_x_continuous(trans = "log10")

Upper again.

Can we find outliers among umis after already filtering out mito and genes?

all.aggr$log.umi <- log10(all.aggr$nCount_RNA)
median.umi <- median(all.aggr@meta.data %>% filter(mito.out == FALSE) %>% filter(gene.out == FALSE) %>% pull(log.umi))
all.aggr$d.umi <- abs(all.aggr$log.umi - median.umi)
md.umi <- mad(all.aggr@meta.data %>% filter(mito.out == FALSE) %>% filter(gene.out == FALSE) %>% pull(log.umi))
all.aggr$umi.out <- all.aggr$d.umi > md.umi*3
sum(all.aggr$umi.out)
[1] 197

So another 197 cells after already filering out outliers from mito and genes.

Where do these lie along umis?

ggplot(data = all.aggr@meta.data %>% filter(mito.out == FALSE) %>% filter(gene.out == FALSE), mapping = aes(x = nCount_RNA, color = umi.out)) +
  geom_histogram() +
  scale_x_continuous(trans = "log10")

Hard to see where these are.

Plot dots.

ggplot(data = all.aggr@meta.data %>% filter(mito.out == FALSE) %>% filter(gene.out == FALSE), mapping = aes(x = nCount_RNA, y = 1, color = umi.out)) +
  geom_point(position = position_jitter(), size = 0.1) +
  scale_x_continuous(trans = "log10")

So some upper and some lower range cells.

So a total of 197 for umi, 221 for gene, and 2256 for mito totaling 2511 cells. There is some overlap.

But there may be some overlap. Which cells are out for any one of these reasons?

all.aggr$all.out <- (all.aggr$mito.out == TRUE | all.aggr$gene.out == TRUE | all.aggr$umi.out == TRUE)
sum(all.aggr$all.out)
[1] 2511

So those are the cells to filter out.

Where are these cells along mito and genes?

ggplot(data = all.aggr@meta.data, mapping = aes(x = percent.mt, y = nFeature_RNA, color = all.out)) +
  geom_point(size = 0.1) +
  scale_x_continuous(trans = "log10")

ggplot(data = all.aggr@meta.data, mapping = aes(x = percent.mt, y = nFeature_RNA, color = all.out)) +
  geom_point(size = 0.1) +
  scale_x_continuous(trans = "log10") + 
  facet_wrap(~embryo.id)

How about along gene and umi?

ggplot(data = all.aggr@meta.data, mapping = aes(x = nCount_RNA, y = nFeature_RNA, color = all.out)) +
  geom_point(size = 0.1) +
  scale_x_continuous(trans = "log10") +
  facet_wrap(~all.out)

ggplot(data = all.aggr@meta.data, mapping = aes(x = nCount_RNA, y = nFeature_RNA, color = all.out)) +
  geom_point(size = 0.1) +
  scale_x_continuous(trans = "log10") +
  facet_wrap(~embryo.id)

Let’s remove those cells.

all.out <- all.aggr$all.out
save(all.out, file = "/Volumes/Bud_SSD/20210505-seurat/all-out-all-aggr.Robj")
scp /Volumes/Bud_SSD/20210505-seurat/all-out-all-aggr.Robj schea2@hpc3.rcic.uci.edu:/dfs6/pub/schea2/20210505-seurat
LS0tCnRpdGxlOiAiV2hpY2ggY2VsbHMgYXJlIGxvdyBxdWFsaXR5IGNlbGxzPyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKTG9hZCBsaWJyYXJpZXMuCmBgYHtyfQpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocHJhY21hKQpgYGAKCkxvYWQgc2V1cmF0IG9iamVjdC4KYGBge3J9CmxvYWQoIi9Wb2x1bWVzL0J1ZF9TU0QvMjAyMTA1MDUtc2V1cmF0L2FsbC1hZ2dyLXNldXJhdC5Sb2JqIikKYGBgCgpFeHBsb3JlIG1ldGEgZGF0YS4KYGBge3J9CmhlYWQoYWxsLmFnZ3JAbWV0YS5kYXRhKQpgYGAKClBsb3QgaGlzdG9ncmFtIG9mIG51bWJlciBvZiB1bWkncy4KYGBge3J9CmdncGxvdChkYXRhID0gYWxsLmFnZ3JAbWV0YS5kYXRhLCBtYXBwaW5nID0gYWVzKHggPSBuQ291bnRfUk5BKSkgKwogIGdlb21faGlzdG9ncmFtKCkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1lYW4oYWxsLmFnZ3IkbkNvdW50X1JOQSksIGNvbG9yID0gImJsdWUiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbWVkaWFuKGFsbC5hZ2dyJG5Db3VudF9STkEpLCBjb2xvciA9ICJyZWQiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIikKYGBgCkxvb2tzIG5vcm1hbCBleGNlcHQgZm9yIGJ1bXAgb24gbGVmdC4KClBsb3QgaGlzdG9ncmFtIG9mIG51bWJlciBvZiB1bWkncy4gQ29sb3IgYnkgZW1icnlvLgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBhbGwuYWdnckBtZXRhLmRhdGEsIG1hcHBpbmcgPSBhZXMoeCA9IG5Db3VudF9STkEsIGNvbG9yID0gZW1icnlvLmlkKSkgKwogIGdlb21faGlzdG9ncmFtKCkgKwogIHNjYWxlX3hfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIpICsgCiAgZmFjZXRfd3JhcCh+ZW1icnlvLmlkKQpgYGAKQnVtcCBvbiBsZWZ0IGR1ZSB0byBBVFU2LTQ1IGFuZCBCQkg2LTU5LgoKV2hhdCBhcmUgdGhlIGdlbm90eXBlcyBvZiB0aGVzZSB0d28gZW1icnlvcz8gV2hpY2ggZXhwZXJpbWVudHMgZGlkIHRoZXkgY29tZSBmcm9tPwpgYGB7cn0KcHJpbnQoIkFUVTYtNDUiKQooYWxsLmFnZ3JAbWV0YS5kYXRhICU+JSBmaWx0ZXIoZW1icnlvLmlkID09ICJBVFU2LTQ1IikgJT4lIHB1bGwoZ2Vub3R5cGUpKVsxXQooYWxsLmFnZ3JAbWV0YS5kYXRhICU+JSBmaWx0ZXIoZW1icnlvLmlkID09ICJBVFU2LTQ1IikgJT4lIHB1bGwoZXhwZXJpbWVudCkpWzFdCgpwcmludCgiQVlSNC0yMiIpCihhbGwuYWdnckBtZXRhLmRhdGEgJT4lIGZpbHRlcihlbWJyeW8uaWQgPT0gIkFZUjQtMjIiKSAlPiUgcHVsbChnZW5vdHlwZSkpWzFdCihhbGwuYWdnckBtZXRhLmRhdGEgJT4lIGZpbHRlcihlbWJyeW8uaWQgPT0gIkFZUjQtMjIiKSAlPiUgcHVsbChleHBlcmltZW50KSlbMV0KYGBgCkJvdGggbXV0YW50LiBCdXQgZnJvbSB0d28gZGlmZmVyZW50IGV4cGVyaW1lbnRzLgoKUGxvdCBoaXN0b2dyYW0gb2YgbnVtYmVyIG9mIGdlbmVzLgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBhbGwuYWdnckBtZXRhLmRhdGEsIG1hcHBpbmcgPSBhZXMoeCA9IG5GZWF0dXJlX1JOQSkpICsKICAgIGdlb21faGlzdG9ncmFtKCkgKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbWVhbihhbGwuYWdnciRuRmVhdHVyZV9STkEpLCBjb2xvciA9ICJibHVlIikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1lZGlhbihhbGwuYWdnciRuRmVhdHVyZV9STkEpLCBjb2xvciA9ICJyZWQiKQoKYGBgCkxvb2tzIHNpbWlsYXIgdG8gaGlzdG9ncmFtIG9mIG51bWJlciBvZiB1bWkncy4gTW9yZSBub3JtYWwuIEV4Y2VwdCBmb3IgYnVtcCBvbiBsZWZ0IGFnYWluLgoKUGxvdCBoaXN0b2dyYW0gb2YgbnVtYmVyIG9mIGdlbmVzLiBDb2xvciBieSBlbWJyeW8uCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGFsbC5hZ2dyQG1ldGEuZGF0YSwgbWFwcGluZyA9IGFlcyh4ID0gbkZlYXR1cmVfUk5BLCBjb2xvciA9IGVtYnJ5by5pZCkpICsKICBnZW9tX2hpc3RvZ3JhbSgpICsKICBmYWNldF93cmFwKH5lbWJyeW8uaWQpCmBgYApCdW1wIGlzIGR1ZSB0byBzYW1lIHR3byBlbWJyeW9zIGVhcmxpZXIuIEFUVTYtNDUgYW5kIEFZUjQtMjIuIAoKQ2FsY3VsYXRlICUgbWl0b2Nob25kcmlhbCBnZW5lcy4KYGBge3J9CmFsbC5hZ2dyW1sicGVyY2VudC5tdCJdXSA8LSBQZXJjZW50YWdlRmVhdHVyZVNldChhbGwuYWdnciwgcGF0dGVybiA9ICJebXQtIikKaGVhZChhbGwuYWdnckBtZXRhLmRhdGEpCmBgYAoKUGxvdCBoaXN0b2dyYW0gb2YgJSBtaXRvY2hvbmRyaWFsIGdlbmVzLgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBhbGwuYWdnckBtZXRhLmRhdGEsIG1hcHBpbmcgPSBhZXMoeCA9IHBlcmNlbnQubXQpKSArCiAgZ2VvbV9oaXN0b2dyYW0oKSArCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBtZWFuKGFsbC5hZ2dyJHBlcmNlbnQubXQpLCBjb2xvciA9ICJibHVlIikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1lZGlhbihhbGwuYWdnciRwZXJjZW50Lm10KSwgY29sb3IgPSAicmVkIikgKwogIHNjYWxlX3hfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIpCmBgYApMYXJnZXN0IHBvcnRpb24gb2YgZGlzdHJpYnV0aW9uIG5vcm1hbC4gT2J2aW91cyBodW1wIG9mIGNlbGxzIHdpdGggbG93ICUgbWl0b2Nob25kcmlhbCBnZW5lcy4gT2RkIHRoYXQgdGhleSBoYXZlIGxvdyAlIG1pdG9jaG9uZHJpYWwgZ2VuZXMuIFVzdWFsbHkgbG93IGlzIGJldHRlciwgYnV0IGhlcmUsIG1vc3QgY2VsbHMgaGF2ZSBhICUgYmV0d2VlbiAxIGFuZCAxMC4KCkFyZSB0aGVzZSBjZWxscyBhc3NvY2lhdGVkIHdpdGggb25lIGVtYnJ5bz8KYGBge3J9CmdncGxvdChkYXRhID0gYWxsLmFnZ3JAbWV0YS5kYXRhLCBtYXBwaW5nID0gYWVzKHggPSBwZXJjZW50Lm10LCBjb2xvciA9IGVtYnJ5by5pZCkpICsKICBnZW9tX2hpc3RvZ3JhbSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiKSArCiAgZmFjZXRfd3JhcCh+ZW1icnlvLmlkLCBzY2FsZXMgPSAiZnJlZV95IikKYGBgCkxlZnQgYnVtcCBkdWUgdG8gbW9yZSB0aGFuIG9uZSBlbWJyeW8uIFBlcnZhc2l2ZSBmZWF0dXJlLgoKJSBtaXRvY2hvbmRyaWFsIGdlbmVzIGlzIGRlcGVuZGVudCBvbiBudW1iZXIgb2YgZ2VuZXMgZGV0ZWN0ZWQuIERvIHRoZXNlIGNvcnJlcG9uZCB0byBjZWxscyB3aXRoIGxvdyBudW1iZXJzIG9mIGdlbmVzPwpgYGB7cn0KZ2dwbG90KGRhdGEgPSBhbGwuYWdnckBtZXRhLmRhdGEsIG1hcHBpbmcgPSBhZXMoeCA9IHBlcmNlbnQubXQsIHkgPSBuRmVhdHVyZV9STkEpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMC4xKSArCiAgICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1lYW4oYWxsLmFnZ3IkcGVyY2VudC5tdCksIGNvbG9yID0gImJsdWUiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbWVkaWFuKGFsbC5hZ2dyJHBlcmNlbnQubXQpLCBjb2xvciA9ICJyZWQiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIikKYGBgClNvIHRoZSBjZWxscyB3aXRoIGxvdyBtaXRvIHRlbmQgdG8gaGF2ZSBsb3dlciBudW1iZXIgb2YgZ2VuZXMuIG1pdG8gc2VlbXMgdG8gZGlzdHJpYnV0ZSBub3JtYWxseSBhbG9uZyBudW1iZXIgb2YgZ2VuZXMuIEJ1dCBpZiB3ZSBvbmx5IGZpbHRlciB0aGVzZSBvdXQsIGl0IGRvZXNuJ3QgYWNjb3VudCBmb3IgdXBwZXIgcmFuZ2UuIAoKQ2FsY3VsYXRlIG91dGxpZXJzIHVzaW5nIG1lZGlhbiBhYnNvbHV0ZSBkZXZpYXRpb24uCmBgYHtyfQphbGwuYWdnciRsb2cubWl0byA8LSBsb2cxMChhbGwuYWdnciRwZXJjZW50Lm10KQptZWRpYW4ubWl0byA8LSBtZWRpYW4oYWxsLmFnZ3IkbG9nLm1pdG8pCmFsbC5hZ2dyJGQubWl0byA8LSBhYnMoYWxsLmFnZ3IkbG9nLm1pdG8gLSBtZWRpYW4ubWl0bykKbWQubWl0byA8LSBtYWQoYWxsLmFnZ3IkbG9nLm1pdG8pCmFsbC5hZ2dyJG1pdG8ub3V0IDwtIGFsbC5hZ2dyJGQubWl0byA+IG1kLm1pdG8qMwpzdW0oYWxsLmFnZ3IkbWl0by5vdXQpCmBgYAoKYGBge3J9CmdncGxvdChkYXRhID0gYWxsLmFnZ3JAbWV0YS5kYXRhLCBtYXBwaW5nID0gYWVzKHggPSBwZXJjZW50Lm10LCB5ID0gbkZlYXR1cmVfUk5BLCBjb2xvciA9IG1pdG8ub3V0KSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuMSkgKwogIHNjYWxlX3hfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIpCmBgYAoKV2hhdCBkb2VzIGhpc3RvZ3JhbSBvZiAlIG1pdG8gbm93IGxvb2s/CmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGFsbC5hZ2dyQG1ldGEuZGF0YSwgbWFwcGluZyA9IGFlcyh4ID0gcGVyY2VudC5tdCwgY29sb3IgPSBtaXRvLm91dCkpICsKICBnZW9tX2hpc3RvZ3JhbSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiKQpgYGAKCkdlbmVzPwpgYGB7cn0KZ2dwbG90KGRhdGEgPSBhbGwuYWdnckBtZXRhLmRhdGEsIG1hcHBpbmcgPSBhZXMoeCA9IG5GZWF0dXJlX1JOQSwgY29sb3IgPSBtaXRvLm91dCkpICsKICBnZW9tX2hpc3RvZ3JhbSgpCmBgYAoKVU1Jcz8KYGBge3J9CmdncGxvdChkYXRhID0gYWxsLmFnZ3JAbWV0YS5kYXRhLCBtYXBwaW5nID0gYWVzKHggPSBuQ291bnRfUk5BLCBjb2xvciA9IG1pdG8ub3V0KSkgKwogIGdlb21faGlzdG9ncmFtKCkgKwogIHNjYWxlX3hfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIpCmBgYAoKQ2FuIHdlIGZpbmQgb3V0bGllcnMgYW1vbmcgZ2VuZXMgYWZ0ZXIgYWxyZWFkeSBmaWx0ZXJpbmcgb3V0IG91dGxpZXJzIGZyb20gbWl0bz8KYGBge3J9Cm1lZGlhbi5nZW5lIDwtIG1lZGlhbihhbGwuYWdnckBtZXRhLmRhdGEgJT4lIGZpbHRlcihtaXRvLm91dCA9PSBGQUxTRSkgJT4lIHB1bGwobkZlYXR1cmVfUk5BKSkKYWxsLmFnZ3IkZC5nZW5lIDwtIGFicyhhbGwuYWdnciRuRmVhdHVyZV9STkEgLSBtZWRpYW4uZ2VuZSkKbWQuZ2VuZSA8LSBtYWQoYWxsLmFnZ3JAbWV0YS5kYXRhICU+JSBmaWx0ZXIobWl0by5vdXQgPT0gRkFMU0UpICU+JSBwdWxsKG5GZWF0dXJlX1JOQSkpCmFsbC5hZ2dyJGdlbmUub3V0IDwtIGFsbC5hZ2dyJGQuZ2VuZSA+IG1kLmdlbmUqMwpzdW0oYWxsLmFnZ3IkZ2VuZS5vdXQpCmBgYApTbyAyMjEgY2VsbHMgY2FuIGJlIGZpbHRlcmVkIG91dCBhZnRlciBhbHJlYWR5IGZpbHRlcmluZyBvdXQgb3V0bGllcnMgZnJvbSBtaXRvLgoKV2hlcmUgZG8gdGhlc2UgY2VsbHMgbGllIGFsb25nIGhpc3RvZ3JhbSBvZiBudW1iZXIgb2YgZ2VuZXM/CmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGFsbC5hZ2dyQG1ldGEuZGF0YSAlPiUgZmlsdGVyKG1pdG8ub3V0ID09IEZBTFNFKSwgbWFwcGluZyA9IGFlcyh4ID0gbkZlYXR1cmVfUk5BLCBjb2xvciA9IGdlbmUub3V0KSkgKwogIGdlb21faGlzdG9ncmFtKCkKYGBgCkNhcHR1cmVkIHRob3NlIGluIHVwcGVyIHJhbmdlLgoKQWxvbmcgbnVtYmVyIG9mIHVtaXM/CmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGFsbC5hZ2dyQG1ldGEuZGF0YSAlPiUgZmlsdGVyKG1pdG8ub3V0ID09IEZBTFNFKSwgbWFwcGluZyA9IGFlcyh4ID0gbkNvdW50X1JOQSwgY29sb3IgPSBnZW5lLm91dCkpICsKICBnZW9tX2hpc3RvZ3JhbSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiKQpgYGAKVXBwZXIgYWdhaW4uCgpDYW4gd2UgZmluZCBvdXRsaWVycyBhbW9uZyB1bWlzIGFmdGVyIGFscmVhZHkgZmlsdGVyaW5nIG91dCBtaXRvIGFuZCBnZW5lcz8KYGBge3J9CmFsbC5hZ2dyJGxvZy51bWkgPC0gbG9nMTAoYWxsLmFnZ3IkbkNvdW50X1JOQSkKbWVkaWFuLnVtaSA8LSBtZWRpYW4oYWxsLmFnZ3JAbWV0YS5kYXRhICU+JSBmaWx0ZXIobWl0by5vdXQgPT0gRkFMU0UpICU+JSBmaWx0ZXIoZ2VuZS5vdXQgPT0gRkFMU0UpICU+JSBwdWxsKGxvZy51bWkpKQphbGwuYWdnciRkLnVtaSA8LSBhYnMoYWxsLmFnZ3IkbG9nLnVtaSAtIG1lZGlhbi51bWkpCm1kLnVtaSA8LSBtYWQoYWxsLmFnZ3JAbWV0YS5kYXRhICU+JSBmaWx0ZXIobWl0by5vdXQgPT0gRkFMU0UpICU+JSBmaWx0ZXIoZ2VuZS5vdXQgPT0gRkFMU0UpICU+JSBwdWxsKGxvZy51bWkpKQphbGwuYWdnciR1bWkub3V0IDwtIGFsbC5hZ2dyJGQudW1pID4gbWQudW1pKjMKc3VtKGFsbC5hZ2dyJHVtaS5vdXQpCmBgYApTbyBhbm90aGVyIDE5NyBjZWxscyBhZnRlciBhbHJlYWR5IGZpbGVyaW5nIG91dCBvdXRsaWVycyBmcm9tIG1pdG8gYW5kIGdlbmVzLgoKV2hlcmUgZG8gdGhlc2UgbGllIGFsb25nIHVtaXM/CmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGFsbC5hZ2dyQG1ldGEuZGF0YSAlPiUgZmlsdGVyKG1pdG8ub3V0ID09IEZBTFNFKSAlPiUgZmlsdGVyKGdlbmUub3V0ID09IEZBTFNFKSwgbWFwcGluZyA9IGFlcyh4ID0gbkNvdW50X1JOQSwgY29sb3IgPSB1bWkub3V0KSkgKwogIGdlb21faGlzdG9ncmFtKCkgKwogIHNjYWxlX3hfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIpCmBgYApIYXJkIHRvIHNlZSB3aGVyZSB0aGVzZSBhcmUuCgpQbG90IGRvdHMuCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGFsbC5hZ2dyQG1ldGEuZGF0YSAlPiUgZmlsdGVyKG1pdG8ub3V0ID09IEZBTFNFKSAlPiUgZmlsdGVyKGdlbmUub3V0ID09IEZBTFNFKSwgbWFwcGluZyA9IGFlcyh4ID0gbkNvdW50X1JOQSwgeSA9IDEsIGNvbG9yID0gdW1pLm91dCkpICsKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKCksIHNpemUgPSAwLjEpICsKICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiKQpgYGAKU28gc29tZSB1cHBlciBhbmQgc29tZSBsb3dlciByYW5nZSBjZWxscy4gCgpTbyBhIHRvdGFsIG9mIDE5NyBmb3IgdW1pLCAyMjEgZm9yIGdlbmUsIGFuZCAyMjU2IGZvciBtaXRvIHRvdGFsaW5nIDI1MTEgY2VsbHMuIFRoZXJlIGlzIHNvbWUgb3ZlcmxhcC4KCkJ1dCB0aGVyZSBtYXkgYmUgc29tZSBvdmVybGFwLiBXaGljaCBjZWxscyBhcmUgb3V0IGZvciBhbnkgb25lIG9mIHRoZXNlIHJlYXNvbnM/CmBgYHtyfQphbGwuYWdnciRhbGwub3V0IDwtIChhbGwuYWdnciRtaXRvLm91dCA9PSBUUlVFIHwgYWxsLmFnZ3IkZ2VuZS5vdXQgPT0gVFJVRSB8IGFsbC5hZ2dyJHVtaS5vdXQgPT0gVFJVRSkKc3VtKGFsbC5hZ2dyJGFsbC5vdXQpCmBgYApTbyB0aG9zZSBhcmUgdGhlIGNlbGxzIHRvIGZpbHRlciBvdXQuIAoKV2hlcmUgYXJlIHRoZXNlIGNlbGxzIGFsb25nIG1pdG8gYW5kIGdlbmVzPwpgYGB7cn0KZ2dwbG90KGRhdGEgPSBhbGwuYWdnckBtZXRhLmRhdGEsIG1hcHBpbmcgPSBhZXMoeCA9IHBlcmNlbnQubXQsIHkgPSBuRmVhdHVyZV9STkEsIGNvbG9yID0gYWxsLm91dCkpICsKICBnZW9tX3BvaW50KHNpemUgPSAwLjEpICsKICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGFsbC5hZ2dyQG1ldGEuZGF0YSwgbWFwcGluZyA9IGFlcyh4ID0gcGVyY2VudC5tdCwgeSA9IG5GZWF0dXJlX1JOQSwgY29sb3IgPSBhbGwub3V0KSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuMSkgKwogIHNjYWxlX3hfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIpICsgCiAgZmFjZXRfd3JhcCh+ZW1icnlvLmlkKQpgYGAKCkhvdyBhYm91dCBhbG9uZyBnZW5lIGFuZCB1bWk/CmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGFsbC5hZ2dyQG1ldGEuZGF0YSwgbWFwcGluZyA9IGFlcyh4ID0gbkNvdW50X1JOQSwgeSA9IG5GZWF0dXJlX1JOQSwgY29sb3IgPSBhbGwub3V0KSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuMSkgKwogIHNjYWxlX3hfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIpICsKICBmYWNldF93cmFwKH5hbGwub3V0KQpgYGAKCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGFsbC5hZ2dyQG1ldGEuZGF0YSwgbWFwcGluZyA9IGFlcyh4ID0gbkNvdW50X1JOQSwgeSA9IG5GZWF0dXJlX1JOQSwgY29sb3IgPSBhbGwub3V0KSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuMSkgKwogIHNjYWxlX3hfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIpICsKICBmYWNldF93cmFwKH5lbWJyeW8uaWQpCmBgYAoKTGV0J3MgcmVtb3ZlIHRob3NlIGNlbGxzLgpgYGB7cn0KYWxsLm91dCA8LSBhbGwuYWdnciRhbGwub3V0CnNhdmUoYWxsLm91dCwgZmlsZSA9ICIvVm9sdW1lcy9CdWRfU1NELzIwMjEwNTA1LXNldXJhdC9hbGwtb3V0LWFsbC1hZ2dyLlJvYmoiKQpgYGAKCmBgYHtiYXNofQpzY3AgL1ZvbHVtZXMvQnVkX1NTRC8yMDIxMDUwNS1zZXVyYXQvYWxsLW91dC1hbGwtYWdnci5Sb2JqIHNjaGVhMkBocGMzLnJjaWMudWNpLmVkdTovZGZzNi9wdWIvc2NoZWEyLzIwMjEwNTA1LXNldXJhdApgYGAKCg==